﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Naruto.FileStorage.Abstractions;
using Naruto.FileStorage.Object;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Naruto.FileStorage
{
    public class FileStorageMiddleware
    {
        private readonly RequestDelegate next;

        /// <summary>
        /// 请求地址
        /// </summary>
        private readonly PathString requestPath;


        public FileStorageMiddleware(RequestDelegate _next, IOptions<FileStorageOption> fileStorageOption)
        {
            next = _next;
            requestPath = fileStorageOption.Value.RequestPath;
        }

        public async Task InvokeAsync(HttpContext httpContext, IOptions<FileStorageOption> fileStorageOption, IFileStorage fileStorage)
        {
            //验证请求的地址
            if (!httpContext.Request.Path.StartsWithSegments(requestPath, StringComparison.OrdinalIgnoreCase, out var remainPathString))
            {
                await next(httpContext);
                return;
            }
            if (!remainPathString.HasValue)
            {
                BuildStatusCode(httpContext, HttpStatusCode.BadRequest);
                return;
            }
            //移除开头的/
            var remainPath = remainPathString.Value.Substring(1, remainPathString.Value.Length - 1);
            //验证请求方式 调用对应的方法处理
            if (httpContext.Request.Method == HttpMethods.Get)
            {
                var files = await fileStorage.GetFileAsync(remainPath);
                if (files == null || files.Length <= 0)
                {
                    BuildStatusCode(httpContext, HttpStatusCode.NotFound);
                    return;
                }
                await BuildReturnFile(httpContext, files);
            }
            //新增文件
            else if (httpContext.Request.Method == HttpMethods.Put)
            {
                httpContext.Request.EnableBuffering();
                //验证是否上传了文件
                if (httpContext.Request.Form == null || httpContext.Request.Form.Files == null || httpContext.Request.Form.Files.Count <= 0)
                {
                    BuildStatusCode(httpContext, HttpStatusCode.BadRequest);
                    return;
                }
                //获取文件流
                using var fileStream = httpContext.Request.Form.Files[0].OpenReadStream();
                //新增文件资源
                var requestPath = await fileStorage.AddFileAsync(fileStream, remainPath);
                await BuildReturnRequestPath(httpContext, requestPath);
            }
            //删除文件
            else if (httpContext.Request.Method == HttpMethods.Delete)
            {
                await fileStorage.DeleteFileAsync(remainPath);
                BuildStatusCode(httpContext, HttpStatusCode.OK);
            }
            else
            {
                BuildStatusCode(httpContext, HttpStatusCode.MethodNotAllowed);
                return;
            }
        }
        /// <summary>
        /// 返回文件信息
        /// </summary>
        /// <param name="httpContext"></param>
        /// <param name="files"></param>
        /// <returns></returns>
        private async Task BuildReturnFile(HttpContext httpContext, byte[] files)
        {
            //写入缓存
            httpContext.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
            {
                Public = true,
                MaxAge = TimeSpan.FromMinutes(30)
            };
            BuildStatusCode(httpContext, HttpStatusCode.OK);
            //写入文件信息
            await httpContext.Response.Body.WriteAsync(files);
        }
        /// <summary>
        /// 返回请求的地址
        /// </summary>
        /// <param name="httpContext"></param>
        /// <param name="files"></param>
        /// <returns></returns>
        private async Task BuildReturnRequestPath(HttpContext httpContext, string requestPath)
        {
            BuildStatusCode(httpContext, HttpStatusCode.Created);
            if (!string.IsNullOrWhiteSpace(requestPath))
            {
                httpContext.Response.ContentType = "application/json;charset=utf-8";
                //写入请求地址
                await httpContext.Response.Body.WriteAsync(Encoding.UTF8.GetBytes("{\"requestPath\":\"" + requestPath + "\"}"));
            }
        }
        /// <summary>
        /// 构建返回的状态码
        /// </summary>
        /// <returns></returns>

        private void BuildStatusCode(HttpContext context, HttpStatusCode httpStatusCode)
        {
            context.Response.StatusCode = (int)httpStatusCode;
        }
    }

    public static class FileStorageMiddlewareExtension
    {
        /// <summary>
        /// 注入文件存储中间件
        /// </summary>
        public static IApplicationBuilder UseFileStorageMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<FileStorageMiddleware>();
        }

    }

    public static class FileStorageServiceCollectionExtension
    {
        /// <summary>
        /// 注入文件存储的服务信息
        /// </summary>
        /// <param name="services"></param>
        /// <param name="fileStorageOption"></param>
        /// <returns></returns>
        public static IServiceCollection AddFileStorage(this IServiceCollection services, Action<FileStorageOption> fileStorageOption)
        {
            FileStorageOption storageOption = new FileStorageOption();
            fileStorageOption.Invoke(storageOption);
            services.Configure(fileStorageOption);
            //注册扩展
            if (storageOption.Extensions != null && storageOption.Extensions.Count > 0)
            {
                foreach (var item in storageOption.Extensions)
                    item.AddService(services);
            }
            return services;
        }
    }
}
